package core;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

import org.apache.log4j.Logger;

import util.Constants;

public class IfoFile {
    private static Logger LOG = Logger.getLogger("core.IfoFile");
    private String strFileName; // path to the ".ifo" file

    // following properties are stored in ".ifo" file
    private long longWordCount = 0; // number of entries stored in ".idx" file
	private String strSameTypeSequence = Constants.BLANK_STRING;
    private long longIdxFileSize = 0; // sizeof ".idx" file
    
	private String strVersion = Constants.BLANK_STRING; // version of dictionary
    private String strBookname = Constants.BLANK_STRING; // name of dictionary
    private String strAuthor = Constants.BLANK_STRING;
	private String strWebsite = Constants.BLANK_STRING;
    private String strDescription = Constants.BLANK_STRING;
    private String strDate = Constants.BLANK_STRING;
    
    public boolean boolIsLoaded = false; // decide if ".ifo" file is loaded
    
    public long getLongWordCount() {
		return longWordCount;
	}
	public void setLongWordCount(long longWordCount) {
		this.longWordCount = longWordCount;
	}
	public long getLongIdxFileSize() {
		return longIdxFileSize;
	}
	public void setLongIdxFileSize(long longIdxFileSize) {
		this.longIdxFileSize = longIdxFileSize;
	}
    public String getStrBookname() {
		return strBookname;
	}
	public void setStrBookname(String strBookname) {
		this.strBookname = strBookname;
	}
	// Contructor
    public IfoFile(String fileName) {
        this.strFileName = fileName;
        load();
//        System.out.println("ifo" + this.boolIsLoaded);
    }
    // load .ifo file
    public void load() {
        // check if the above properties are loaded
        if (boolIsLoaded) {
            return;
        }
        // load the properties
        try {
            // initiate a file reader
            DataInputStream dt = new DataInputStream(new BufferedInputStream(new FileInputStream(strFileName)));
            byte[] bt = new byte[500];
            dt.read(bt); // read entire info file
            dt.close();
            String strInput = new String(bt, "UTF8"); // convert to utf8 string
            strVersion = getStringForKey("version=", strInput); 
            // get version
            if (strVersion.equals("2.4.2") == false) { // only work on version 2.4.2
                return;
            }
            // get number of entries
            if ((longWordCount = getLongForKey("wordcount=", strInput)) < 0) { // get number of entries and check
                return;
            }
            // get size of ".idx" file
            if ((longIdxFileSize = getLongForKey("idxfilesize=", strInput)) < 0) { // get size of index file and check
                return;
            }
            // get same type sequence
            strSameTypeSequence = getStringForKey("sametypesequence=", strInput);
            // get name of dictionary
            strBookname = getStringForKey("bookname=", strInput); 
            if (strBookname == null) {
                return;
            }
            // get name of author
            strAuthor = getStringForKey("author=", strInput);
            // get name of Website
            strWebsite = getStringForKey("website=", strInput);
            // get description
            strDescription = getStringForKey("description=", strInput);
            strDate = getStringForKey("date=", strInput);
            // make sure that ifo file is loaded successfully	
            boolIsLoaded = longWordCount > 0; 
        } catch (Exception ex) {
            LOG.error("load", ex);
        }
    }

    // load the properties again
    public void reload() {
        boolIsLoaded = false;
        load();
    }

    // find a long number follows the key in a string
    long getLongForKey(String strKey, String str) {
        try {
            return Long.parseLong(getStringForKey(strKey, str));
        } catch (Exception ex) {
            LOG.error("getLongForKey", ex);
            return 0;
        }
    }

    // find a string follows the key in a string
    String getStringForKey(String strKey, String str) {
        int keyLen = strKey.length();
        int startPos = str.indexOf(strKey) + keyLen; 
        if (startPos < keyLen) {
            return null;
        }
        char[] strStr = str.toCharArray();
        int endPos = startPos - 1;
        while (strStr[++endPos] != '\n' && strStr[endPos] != '\0')
            ;
        return new String(strStr, startPos, endPos - startPos);
    }

    // write info file according to a specific file name
    boolean write(String fileName) {
        try {
            FileOutputStream fos = new FileOutputStream(fileName);
            OutputStreamWriter opw = new OutputStreamWriter(fos, "UTF8");
            opw.write("StarDict's dict ifo file\n");
            opw.write("version=" + strVersion + "\n");
            opw.write("wordcount=" + longWordCount + "\n");
            opw.write("idxfilesize=" + longIdxFileSize + "\n");
            opw.write("bookname=" + strBookname + "\n");
            opw.write("author=" + strAuthor + "\n");
            opw.write("website=" + strWebsite + "\n");
            opw.write("description=" + strDescription + "\n");
            opw.write("date=" + strDate + "\n");
            opw.write("sametypesequence=" + strSameTypeSequence + "\n");
            opw.flush();
            opw.close();
            fos.close();
        } catch (Exception ex) {
            LOG.error("write", ex);
            return false;
        }
        return true;
    }

    boolean write() {
        return write(strFileName);
    }
}
